package com.scz.aop;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializeConfig;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.google.common.collect.Lists;
import com.scz.annotation.MyLog;
import com.scz.common.lang.Result;
import com.scz.dto.LoginDto;
import com.scz.dto.OrdersDto;
import com.scz.dto.PorderDto;
import com.scz.dto.log.*;
import com.scz.entity.OrdersItems;
import com.scz.serialization.NullToStringSerializer;
import com.scz.util.BrowserInfoUtils;
import com.scz.util.LogWriterUtil;
import com.scz.util.ServletUtils;
import com.scz.util.UserInfoThreadLocal;
import com.scz.util.ip.IpUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;


@Aspect
@Component
public class LogAspect {
    ;

    @Pointcut("@annotation(com.scz.annotation.MyLog)")
    public void logPointCut() {
    }


    @AfterReturning(pointcut = "logPointCut()", returning = "jsonResult")
    public void doAfterReturning(JoinPoint joinPoint, Object jsonResult) {
        try {
            BaseLogDto logDto = getLogDto();
            // 获取方法签名
            MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
            // 获取目标方法
            Method method = methodSignature.getMethod();
            // 获取方法上的注解
            MyLog myLog = method.getAnnotation(MyLog.class);
            int content = myLog.content();

            switch (content) {
                case 0://登录
                    //获取方法参数
                    logDto = getLoginLogDto(joinPoint, logDto);
                    break;
                case 1://下单
                    logDto = getOrderLogDto(joinPoint, logDto, jsonResult);
                    break;
                case 3://派单
                    logDto = getDispatchLogDto(joinPoint, logDto, jsonResult);
                    break;
                case 4:
                    logDto = getReceiveLogDto(joinPoint, logDto);
                    break;
                default:
                    System.out.println("未知日志类型");
            }
            LogWriterUtil.writeLog(logDto);
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("日志记录失败");
        }
    }

    /**
     * 收货事件日志
     * @param joinPoint
     * @param dto
     * @return
     */
    private BaseLogDto getReceiveLogDto(JoinPoint joinPoint, BaseLogDto dto) {
        // 获取方法签名
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        // 获取目标方法
        Method method = methodSignature.getMethod();
        // 获取参数名称
        String[] parameterNames = methodSignature.getParameterNames();
        ReceiveLogDto receiveLogDto = new ReceiveLogDto();
        // 获取方法的所有参数
        Object[] args = joinPoint.getArgs();
        for (int i = 0; i < parameterNames.length; i++) {
            String parameterName = parameterNames[i];
            if ("username".equals(parameterName)) {
                receiveLogDto.setReceiveName((String) args[i]);
            } else if ("orderId".equals(parameterName)) {
                receiveLogDto.setOrderId((String) args[i]);
                receiveLogDto.setReceiveId((String) args[i]);
            } else {
                continue;
            }
        }

        dto.setEventType("receive");
        dto.setUserId(receiveLogDto.getReceiveName());
        JSONObject eventDetails = new JSONObject();
        eventDetails.put("receive", receiveLogDto);
        dto.setEventDetails(eventDetails);
        return dto;

    }

    /**
     * 处理派单日志
     * @param joinPoint
     * @param dto
     * @param jsonResult
     * @return
     */
    private BaseLogDto getDispatchLogDto(JoinPoint joinPoint, BaseLogDto dto, Object jsonResult) {
        Object[] args = joinPoint.getArgs();
        for (Object arg : args) {
            if (arg instanceof PorderDto) {
                PorderDto porderDto = (PorderDto) arg;
                DispatchLogDto dispatchLogDto = new DispatchLogDto();
                dispatchLogDto.setDispatchId(porderDto.getOrderId());
                dispatchLogDto.setOrderId(porderDto.getOrderId());
                DispatchLogDto.EmployeeDTO employeeDTO = new DispatchLogDto.EmployeeDTO();
                employeeDTO.setName(porderDto.getEmp());
                employeeDTO.setCompany(porderDto.getEmpCompany());
                employeeDTO.setPhone(porderDto.getEmpPhone());
                dispatchLogDto.setEmployee(employeeDTO);
                String username = porderDto.getUsername();
                dto.setEventType("dispatch");
                dto.setUserId(username);

                JSONObject eventDetails = new JSONObject();
                eventDetails.put("dispatch", dispatchLogDto);
                dto.setEventDetails(eventDetails);
                return dto;
            }
        }

        return null;
    }

    /**
     * 处理订单日志
     * @param joinPoint
     * @param dto
     * @return
     */
    private BaseLogDto getOrderLogDto(JoinPoint joinPoint, BaseLogDto dto, Object jsonResult) {
        Object[] args = joinPoint.getArgs();
        OrdersDto ordersDto = null;
        for (Object arg : args) {
            if (arg instanceof OrdersDto) {
                ordersDto = (OrdersDto) arg;
                OrderLogDto orderLogDto = new OrderLogDto();
                //状态
                orderLogDto.setStatus(1);
                //收货名称
                orderLogDto.setReceiptName(ordersDto.getReceiptName());
                //收货地址
                orderLogDto.setReceiptAddress(ordersDto.getReceiptAddress() + "/" + ordersDto.getDetailsAddress());
                //总金额
                orderLogDto.setTotalAmount(ordersDto.getPayment().doubleValue());
                //获取订单id
                if (jsonResult instanceof Result) {
                    Result result = (Result) jsonResult;
                    String orderId = result.getData().get("orderId").toString();
                    orderLogDto.setOrderId(orderId);
                }

                List<OrdersItems> drugs = ordersDto.getDrugs();
                List<OrderLogDto.ProductsDTO> productsDTOList = new ArrayList<>(drugs.size());
                for (OrdersItems ordersItems : drugs) {
                    OrderLogDto.ProductsDTO productsDTO = new OrderLogDto.ProductsDTO();
                    productsDTO.setProductId(ordersItems.getDrugName());
                    productsDTO.setProductName(ordersItems.getDrugName());
                    productsDTO.setQuantity(ordersItems.getAmount());
                    productsDTO.setPrice(ordersItems.getPrice().doubleValue());
                    productsDTOList.add(productsDTO);
                }
                orderLogDto.setProducts(productsDTOList);
                dto.setEventType("order");
                dto.setUserId(ordersDto.getUsername());
                JSONObject eventDetails = new JSONObject();
                eventDetails.put("order", orderLogDto);
                dto.setEventDetails(eventDetails);
                return dto;
            }
        }
        return null;
    }

    /**
     * 记录登录日志
     * @param joinPoint
     * @param dto
     * @return
     */
    private BaseLogDto getLoginLogDto(JoinPoint joinPoint, BaseLogDto dto) {
        Object[] args = joinPoint.getArgs();
        for (Object arg : args) {
            if (arg instanceof LoginDto) {
                //获取登录信息
                LoginDto loginDto = (LoginDto) arg;
                dto.setEventType("login");
                dto.setUserId(loginDto.getUsername());
                LoginLogDto loginLogDto = new LoginLogDto();
                loginLogDto.setLogingMethod("password");
                JSONObject eventDetails = new JSONObject();
                eventDetails.put("login", loginLogDto);
                dto.setEventDetails(eventDetails);
                return dto;
            }
        }
        return null;
    }

    /**
     * 通用日志字段
     * @return
     */
    private BaseLogDto getLogDto() {
        BaseLogDto baseLogDto = new BaseLogDto();
        //记录ip
        String ipAddr = IpUtils.getIpAddr();
        //记录浏览器信息
        String browserInfo = BrowserInfoUtils.getBrowserInfo();
        //记录操作系统信息
        String os = BrowserInfoUtils.getOperatingSystemInfo();
        String platform = BrowserInfoUtils.getPlatform();
        baseLogDto.setEventId(UUID.randomUUID().toString());
        baseLogDto.setIpAddress(ipAddr);
        baseLogDto.setPlatform(platform);
        baseLogDto.setTimestamp(new Date().getTime() + "");
        baseLogDto.setSessionId(ServletUtils.getSession().getId());
        BaseLogDto.DeviceInfoDTO deviceInfoDTO = new BaseLogDto.DeviceInfoDTO();
        deviceInfoDTO.setBrowser(browserInfo);
        deviceInfoDTO.setOs(os);
        deviceInfoDTO.setDeviceType(os);
        baseLogDto.setDeviceInfo(deviceInfoDTO);
        return baseLogDto;
    }


}